package top.lshaci.learning.springboot.aop.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

/**
 * WebLogAspect
 *
 * @author lshaci
 * @since 1.0.0
 */
@Slf4j
@Aspect
@Component
public class WebLogAspect {

    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping) || " +
            "@annotation(org.springframework.web.bind.annotation.PostMapping) || " +
            "@annotation(org.springframework.web.bind.annotation.PutMapping) || " +
            "@annotation(org.springframework.web.bind.annotation.DeleteMapping) || " +
            "@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void pointcut() {

    }

    @Around("pointcut() && execution(public * top.lshaci.learning.springboot.aop..*.*(..))")
    public Object weblog(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            return joinPoint.proceed();
        } finally {
            Object target = joinPoint.getTarget();
            Signature signature = joinPoint.getSignature();
            String methodName = signature.getName();
            long end = System.currentTimeMillis();
            log.debug("URI: {}, target: {}, methodName:{}, 耗时: {}ms", uri(), target.getClass().getName(), methodName, end - start);
        }
    }

    private String uri() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        return Optional.ofNullable(requestAttributes)
                .map(ServletRequestAttributes::getRequest)
                .map(HttpServletRequest::getRequestURI)
                .orElse(null);

    }
}
